package bma.common.thrift.ai;

import org.apache.thrift.TApplicationException;
import org.apache.thrift.TBase;
import org.apache.thrift.TException;
import org.apache.thrift.TFieldIdEnum;
import org.apache.thrift.protocol.TMessage;
import org.apache.thrift.protocol.TMessageType;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TTransportException;

import bma.common.langutil.ai.AIUtil;
import bma.common.langutil.ai.stack.AIStack;

public class TAIBaseServiceClient {

	protected AIThriftInvoker invoker;
	protected String moduleName;
	protected int seqId;

	public TAIBaseServiceClient(AIThriftInvoker invoker, String module) {
		super();
		this.invoker = invoker;
		this.moduleName = module;
	}

	public <TYPE> boolean invoke(AIStack<TYPE> stack, final TBase result,
			final String name, final TBase avgs) {
		seqId++;
		try {
			return invoker.invoke(stack, seqId, result, moduleName, name, avgs);
		} catch (Exception e) {
			return AIUtil.safeFailure(stack, e);
		}
	}

	static final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(TAIBaseServiceClient.class);

	public static void sendBase(TProtocol out, String name, TBase avgs,
			final int seqid) throws TException, TTransportException {
		// log.info("sendBase {} - {}", seqid, name);
		out.writeMessageBegin(new TMessage(name, TMessageType.CALL, seqid));
		avgs.write(out);
		out.writeMessageEnd();
		out.getTransport().flush();
	}

	public static <TYPE> void readBase(AIStack<TYPE> stack, TProtocol in,
			int seqid, String name, TBase result) throws TException {
		// log.info("readBase {} - {}", seqid, name);
		// if(seqid==2) {
		// seqid = 2;
		// }
		TMessage msg = in.readMessageBegin();
		if (msg.type == TMessageType.EXCEPTION) {
			TApplicationException x = TApplicationException.read(in);
			in.readMessageEnd();
			throw x;
		}
		if (msg.seqid != seqid) {
			throw new TApplicationException(
					TApplicationException.BAD_SEQUENCE_ID, name
							+ " failed: out of sequence response (" + msg.seqid
							+ "/" + seqid + ")");
		}
		result.read(in);
		in.readMessageEnd();
		TFieldIdEnum field = result.fieldForId(0);
		if (field != null) {
			stack.success((TYPE) result.getFieldValue(field));
		} else {
			stack.success(null);
		}
	}
}
